#include "CDXManager.h"
#include "CVSView.h"

namespace Framework
{
	CDXManager::CDXManager()
	{
		m_pD3D = NULL;
		m_pD3DDevice = NULL;

		m_pD3DInput=NULL;
		m_pKeyboardDevice=NULL;
	}

	bool CDXManager::InitDirectX(HWND hWnd)
	{
		m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
		if (m_pD3D == NULL)
		{	
			ErrorTrace(L"Error can't create Direct3D!");
			return false;
		}

		m_pD3DPP.BackBufferWidth = CVSView::GetInstance()->GetWidth();
		m_pD3DPP.BackBufferHeight = CVSView::GetInstance()->GetHeight();
		m_pD3DPP.BackBufferFormat = D3DFMT_X8R8G8B8;
		m_pD3DPP.BackBufferCount = 1;
		m_pD3DPP.MultiSampleType = D3DMULTISAMPLE_NONE;
		m_pD3DPP.MultiSampleQuality = 0;
		m_pD3DPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
		m_pD3DPP.hDeviceWindow = hWnd;
		m_pD3DPP.Windowed = true;
		m_pD3DPP.EnableAutoDepthStencil = 0;
		m_pD3DPP.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
		m_pD3DPP.Flags = 0;
		m_pD3DPP.FullScreen_RefreshRateInHz = 0;
		m_pD3DPP.PresentationInterval = 0;

		// Create Direct3D Device
		m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			hWnd, 
			D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
			&m_pD3DPP, 
			&m_pD3DDevice);
		if (m_pD3DDevice == NULL)
		{	
			ErrorTrace(L"Error can't create Direct3D Device!");
			return false;
		}
		D3DXCreateSprite(m_pD3DDevice,&m_pDXSprite);
		return true;
	}
	CDXManager::~CDXManager(void)
	{
		if (m_pD3DDevice != NULL)
		{	
			m_pD3DDevice->Release();
			m_pD3DDevice = NULL;
		}
		if (m_pD3D != NULL)
		{	
			m_pD3D->Release();
			m_pD3D = NULL;
		}
	}
	LPDIRECT3DSURFACE9 CDXManager::LoadSurface(char *filename)
	{
		D3DXIMAGE_INFO infoImg;
		HRESULT result;
		result = D3DXGetImageInfoFromFile(filename, &infoImg);
		if (result != D3D_OK)
			return NULL;
		result = m_pD3DDevice->CreateOffscreenPlainSurface(
			infoImg.Width,         
			infoImg.Height,        
			D3DFMT_X8R8G8B8,   
			D3DPOOL_DEFAULT,    
			&m_pSurface,             
			NULL);             

		if (result != D3D_OK)
			return NULL;

		result = D3DXLoadSurfaceFromFile(
			m_pSurface,             
			NULL,          
			NULL,          
			filename,          
			NULL,              
			D3DX_DEFAULT,       
			D3DCOLOR_XRGB(0,0,255),         
			NULL);            

		if (result != D3D_OK)
			return NULL;

		return m_pSurface;
	}
	void CDXManager::BeginRender()
	{
		if (m_pD3DDevice == NULL)
			return ;
		if FAILED(m_pD3DDevice->BeginScene())
			return ;
		m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
	}
	void CDXManager::RenderSurface()
	{
		if (m_pD3DDevice!=NULL)
		{
			IDirect3DSurface9* pBackBuffer=NULL;		
			m_pD3DDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
			m_pD3DDevice->StretchRect(m_pSurface,NULL,pBackBuffer,NULL,D3DTEXF_NONE);
		}
		return ;
	}
	void CDXManager::EndRender()
	{
		if (m_pD3DDevice == NULL)
			return ;
		if FAILED(m_pD3DDevice->EndScene())
			return ;
		if FAILED(m_pD3DDevice->Present(NULL, NULL, NULL, NULL))
			return;
	}

	bool CDXManager::InitKeyboardDevice(HINSTANCE hInst)
	{
		HRESULT hResult=DirectInput8Create(hInst,DIRECTINPUT_VERSION,IID_IDirectInput8, (VOID**)&m_pD3DInput, NULL);
		if(hResult!=DI_OK)
		{
			ErrorTrace(L"DirectInput has not been created");
			return false;
		}
		ErrorTrace(L"DirectInput has been created");
		hResult=m_pD3DInput->CreateDevice(GUID_SysKeyboard, &m_pKeyboardDevice, NULL); 
		if(hResult!=DI_OK)
		{
			return false;
		}

		ErrorTrace(L"DirectInput keyboard has been created");
		hResult=m_pKeyboardDevice->SetDataFormat(&c_dfDIKeyboard);

		if(hResult!=DI_OK)
		{
			return false;
		}
		ErrorTrace(L"SetDataFormat for keyboard successfully");

		hResult = m_pKeyboardDevice->SetCooperativeLevel(CVSView::GetInstance()->GethWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 

		ErrorTrace(L"SetCooperativeLevel for keyboard successfully");

		DIPROPDWORD dipdw;
		dipdw.diph.dwSize=sizeof(DIPROPDWORD);
		dipdw.diph.dwHeaderSize=sizeof(DIPROPHEADER);
		dipdw.diph.dwObj=0;
		dipdw.diph.dwHow=DIPH_DEVICE;
		dipdw.dwData= KEYBOARD_BUFFER_SIZE;
		// set proferty sucessful
		hResult=m_pKeyboardDevice->SetProperty(DIPROP_BUFFERSIZE,&dipdw.diph);
		if(hResult!=DI_OK)
		{
			return false;
		}
		ErrorTrace(L"Set proferties Keyboard sucessful ");
		hResult=m_pKeyboardDevice->Acquire();
		if(hResult!=DI_OK)
		{
			return false;
		}
		ErrorTrace(L"Keyboard has been acquired successfully");
		return true;
	}

	void CDXManager::ProcessKeyBoard()
	{

		m_pKeyboardDevice->GetDeviceState( sizeof(KeyStates),  KeyStates);

		ErrorTrace(L"GetDeviceState done!");

		if (IsKeyDown(DIK_ESCAPE)) 
		{
			ErrorTrace(L"Escape key pressed!");
			PostMessage(CVSView::GetInstance()->GethWnd(),WM_QUIT,0,0);
		}

		// Collect all buffered events
		DWORD dwElements = KEYBOARD_BUFFER_SIZE;
		HRESULT hr = m_pKeyboardDevice->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), KeyEvents, &dwElements, 0 );

		// Scan through all data, check if the key is pressed or released
		for( DWORD i = 0; i < dwElements; i++ ) 
		{
			int KeyCode = KeyEvents[i].dwOfs;
			int KeyState = KeyEvents[i].dwData;
			if ( (KeyState & 0x80) > 0)
				OnKeyDown(KeyCode);
			else 
				OnKeyUp(KeyCode);
		}
	}

	int CDXManager::IsKeyDown( int KeyCode )
	{
		return (KeyStates[KeyCode] & 0x80) > 0;
	}

}
